/** 
 * Project Name:hy_utils 
 * File Name:UpdateHelper.java 
 * Package Name:com.hy.utils.updatehelper 
 * Date:2016-3-9下午4:31:10 
 * Copyright (c) 2016, 1114545339@qq.com All Rights Reserved. 
 * 
 */
package com.hy.utils.updatehelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.google.gson.Gson;
import com.hy.utils.http.HttpUtils;
import com.hy.utils.http.HttpUtils.DownloadListener;
import com.hy.utils.task.ResultAsyncTask;

import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;

/**
 * 检查更新工具类  
 * @author wang
 */
public class ApplicationUpdateHelper {

	private Context mContext;
	private String checkUrl;
	//是否拼装URL
	private String assemblyUrl;
	private boolean isAutoInstall;
	private boolean isHintVersion;
	private OnUpdateListener updateListener;
	private NotificationManager notificationManager;
	private NotificationCompat.Builder ntfBuilder;

	private static final int UPDATE_NOTIFICATION_PROGRESS = 0x1;
	private static final int COMPLETE_DOWNLOAD_APK = 0x2;
	private static final int DOWNLOAD_NOTIFICATION_ID = 0x3;
	private static final String PATH = Environment
			.getExternalStorageDirectory().getPath();
	private static final String SUFFIX = ".apk";
	private static final String APK_PATH = "APK_PATH";
	private static final String APP_NAME = "APP_NAME";
	private SharedPreferences preferences_update;

	private HashMap<String, String> cache = new HashMap<String, String>();

	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case UPDATE_NOTIFICATION_PROGRESS:
				showDownloadNotificationUI((UpdateInfo) msg.obj, msg.arg1);
				break;
			case COMPLETE_DOWNLOAD_APK:
				if (ApplicationUpdateHelper.this.isAutoInstall) {
					installApk(Uri.parse("file://" + cache.get(APK_PATH)));
				} else {
					if (ntfBuilder == null) {
						ntfBuilder = new NotificationCompat.Builder(mContext);
					}
					ntfBuilder.setSmallIcon(mContext.getApplicationInfo().icon)
							.setContentTitle(cache.get(APP_NAME))
							.setContentText("下载完成，点击安装").setTicker("任务下载完成");
					Intent intent = new Intent(Intent.ACTION_VIEW);
					intent.setDataAndType(
							Uri.parse("file://" + cache.get(APK_PATH)),
							"application/vnd.android.package-archive");
					PendingIntent pendingIntent = PendingIntent.getActivity(
							mContext, 0, intent, 0);
					ntfBuilder.setContentIntent(pendingIntent);
					if (notificationManager == null) {
						notificationManager = (NotificationManager) mContext
								.getSystemService(Context.NOTIFICATION_SERVICE);
					}
					notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,
							ntfBuilder.build());
				}
				break;
			}
		}

	};

	private ApplicationUpdateHelper(Builder builder) {
		this.mContext = builder.context;
		this.checkUrl = builder.checkUrl;
		this.isAutoInstall = builder.isAutoInstall;
		this.isHintVersion = builder.isHintNewVersion;
		this.assemblyUrl=builder.assemblyUrl;
		preferences_update = mContext.getSharedPreferences("Updater",
				Context.MODE_PRIVATE);
	}

	/**
	 * 检查app是否有新版本，check之前先Builer所需参数
	 */
	public void check() {
		check(null);
	}

	public void check(OnUpdateListener listener) {
		if (listener != null) {
			this.updateListener = listener;
		}
		if (mContext == null) {
			Log.e("NullPointerException", "The context must not be null.");
			return;
		}
		asynccheck();
	}

	/**
	 * 2014-10-27新增流量提示框，当网络为数据流量方式时，下载就会弹出此对话框提示
	 * 
	 * @param updateInfo
	 */
	private void showNetDialog(final UpdateInfo updateInfo) {
		AlertDialog.Builder netBuilder = new AlertDialog.Builder(mContext);
		netBuilder.setTitle("下载提示");
		netBuilder.setMessage("您在目前的网络环境下继续下载将可能会消耗手机流量，请确认是否继续下载？");
		netBuilder.setNegativeButton("取消下载",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				});
		netBuilder.setPositiveButton("继续下载",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						asyncdownload(updateInfo);
					}
				});
		AlertDialog netDialog = netBuilder.create();
		netDialog.setCanceledOnTouchOutside(false);
		netDialog.show();
	}

	/**
	 * 弹出提示更新窗口
	 * 
	 * @param updateInfo
	 */
	private void showUpdateUI(final UpdateInfo updateInfo) {
		AlertDialog.Builder upDialogBuilder = new AlertDialog.Builder(mContext);
		upDialogBuilder.setTitle(updateInfo.getUpdateTips());
		upDialogBuilder.setMessage(updateInfo.getChangeLog());
		upDialogBuilder.setNegativeButton("下次再说",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				});
		upDialogBuilder.setPositiveButton("下载",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						NetWorkUtils netWorkUtils = new NetWorkUtils(mContext);
						int type = netWorkUtils.getNetType();
						if (type != 1) {
							showNetDialog(updateInfo);
						} else {
				          asyncdownload(updateInfo);
						}
					}
				});
		AlertDialog updateDialog = upDialogBuilder.create();
		updateDialog.setCanceledOnTouchOutside(false);
		updateDialog.show();
	}

	/**
	 * 通知栏弹出下载提示进度
	 * 
	 * @param updateInfo
	 * @param progress
	 */
	private void showDownloadNotificationUI(UpdateInfo updateInfo,
			final int progress) {
		if (mContext != null) {
			String contentText = new StringBuffer().append(progress)
					.append("%").toString();
			PendingIntent contentIntent = PendingIntent.getActivity(mContext,
					0, new Intent(), PendingIntent.FLAG_CANCEL_CURRENT);
			if (notificationManager == null) {
				notificationManager = (NotificationManager) mContext
						.getSystemService(Context.NOTIFICATION_SERVICE);
			}
			if (ntfBuilder == null) {
				ntfBuilder = new NotificationCompat.Builder(mContext)
						.setSmallIcon(mContext.getApplicationInfo().icon)
						.setTicker("开始下载...")
						.setContentTitle(updateInfo.getAppName())
						.setContentIntent(contentIntent);
			}
			ntfBuilder.setContentText(contentText);
			ntfBuilder.setProgress(100, progress, false);
			notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,
					ntfBuilder.build());
		}
	}

	/**
	 * 获取当前app版本
	 * 
	 * @return
	 * @throws android.content.pm.PackageManager.NameNotFoundException
	 */
	private PackageInfo getPackageInfo() {
		PackageInfo pinfo = null;
		if (mContext != null) {
			try {
				pinfo = mContext.getPackageManager().getPackageInfo(
						mContext.getPackageName(), 0);
			} catch (PackageManager.NameNotFoundException e) {
				e.printStackTrace();
			}
		}
		return pinfo;
	}

	/**
	 * 检查更新任务
	 */
	private void asynccheck() {
		new ResultAsyncTask<UpdateInfo>(mContext) {

			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				if (ApplicationUpdateHelper.this.updateListener != null) {
					ApplicationUpdateHelper.this.updateListener.onStartCheck();
				}
			}

			@Override
			protected void onPostExecuteSuc(UpdateInfo updateInfo) {
				SharedPreferences.Editor editor = preferences_update.edit();
				if (mContext != null && updateInfo != null) {
					if (Integer.parseInt(updateInfo.getVersionCode()) > getPackageInfo().versionCode) {
						showUpdateUI(updateInfo);
						editor.putBoolean("hasNewVersion", true);
						editor.putString("lastestVersionCode",
								updateInfo.getVersionCode());
						editor.putString("lastestVersionName",
								updateInfo.getVersionName());
					} else {
						if (isHintVersion) {
							Toast.makeText(mContext, "当前已是最新版",
									Toast.LENGTH_LONG).show();
						}
						editor.putBoolean("hasNewVersion", false);
					}
				} else {
					if (isHintVersion) {
						Toast.makeText(mContext, "当前已是最新版", Toast.LENGTH_LONG)
								.show();
					}
				}
				editor.putString("currentVersionCode",
						getPackageInfo().versionCode + "");
				editor.putString("currentVersionName",
						getPackageInfo().versionName);
				editor.commit();
				if (ApplicationUpdateHelper.this.updateListener != null) {
					ApplicationUpdateHelper.this.updateListener.onFinishCheck(updateInfo);
				}

			}

			@Override
			protected UpdateInfo doInBackground(Void... params) {
				UpdateInfo updateInfo = null;
				String json = HttpUtils.reqForGet(checkUrl);
				updateInfo = new Gson().fromJson(json, UpdateInfo.class);

				return updateInfo;
			}
		}.execute();
	}

	/**
	 * 异步下载app任务
	 */
	private void asyncdownload(final UpdateInfo up) {
		new ResultAsyncTask<Boolean>(mContext) {

			@Override
			protected void onPostExecuteSuc(Boolean result) {
				// TODO Auto-generated method stub
				if (result) {
					handler.obtainMessage(COMPLETE_DOWNLOAD_APK).sendToTarget();
					if (ApplicationUpdateHelper.this.updateListener != null) {
						ApplicationUpdateHelper.this.updateListener.onFinshDownload();
					}
				} else {
					Log.e("Error", "下载失败。");
				}
			}

			@Override
			protected Boolean doInBackground(Void... params) {
				String downloadUrl=up.getApkUrl();
				String apkName = up.getAppName()
						+ up.getVersionName() + SUFFIX;
				if(assemblyUrl!=null){
					downloadUrl=assemblyUrl+up.getApkUrl();
				}
				Log.i("why", assemblyUrl);
				cache.put(APP_NAME, up.getAppName());
				cache.put(APK_PATH,
						PATH + File.separator + up.getAppName()
								+ File.separator + apkName);
				File savePath = new File(PATH + File.separator
						+ up.getAppName());
				if (!savePath.exists())
					savePath.mkdirs();
				File file = new File(savePath, apkName);
				if(file.exists()){
					return true;
				}
				File downloadfile=HttpUtils.reqForDownload(downloadUrl, file, true,
						new DownloadListener() {

							@Override
							public void onDownloading(long loaded, long total) {
								// TODO Auto-generated method stub
								int progress = (int) ((loaded / (float) total) * 100);
								if (progress % 5 == 0) {
									handler.obtainMessage(UPDATE_NOTIFICATION_PROGRESS,
											progress, -1, up).sendToTarget();
								}
								
								if (ApplicationUpdateHelper.this.updateListener != null) {
									ApplicationUpdateHelper.this.updateListener
											.onDownloading(progress);
								}
							}

							@Override
							public void onDownloadFinish(File file) {

							}

							@Override
							public void onDownloadError(String error) {
								
							}
						});
				if(downloadfile!=null){
					return true;
				}else{
					return false;
				}
			
			}

		}.execute();
	}


	public static class Builder {
		private Context context;
		private String checkUrl;
		private String assemblyUrl;
		private boolean isAutoInstall = true;
		private boolean isHintNewVersion = true;

		public Builder(Context ctx) {
			this.context = ctx;
		}

		/**
		 * 检查是否有新版本App的URL接口路径
		 * 
		 * @param checkUrl
		 * @return
		 */
		public Builder checkUrl(String checkUrl) {
			this.checkUrl = checkUrl;
			return this;
		}
		
		public Builder assemblyUrl(String assemblyUrl){
			this.assemblyUrl=assemblyUrl;
			return this;
		}

		/**
		 * 是否需要自动安装, 不设置默认自动安装
		 * 
		 * @param isAuto
		 *            true下载完成后自动安装，false下载完成后需在通知栏手动点击安装
		 * @return
		 */
		public Builder isAutoInstall(boolean isAuto) {
			this.isAutoInstall = isAuto;
			return this;
		}

		/**
		 * 当没有新版本时，是否Toast提示
		 * 
		 * @param isHint
		 * @return true提示，false不提示
		 */
		public Builder isHintNewVersion(boolean isHint) {
			this.isHintNewVersion = isHint;
			return this;
		}

		/**
		 * 构造UpdateManager对象
		 * 
		 * @return
		 */
		public ApplicationUpdateHelper build() {
			return new ApplicationUpdateHelper(this);
		}
	}

	private void installApk(Uri data) {
		if (mContext != null) {
			Intent i = new Intent(Intent.ACTION_VIEW);
			i.setDataAndType(data, "application/vnd.android.package-archive");
			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			mContext.startActivity(i);
			if (notificationManager != null) {
				notificationManager.cancel(DOWNLOAD_NOTIFICATION_ID);
			}
		} else {
			Log.e("NullPointerException", "The context must not be null.");
		}

	}

}
